#include <chrono>
#include <functional>
#include <memory>
#include <string>

#include "rclcpp/rclcpp.hpp"//ROS2中常用C++接口的头文件，使用C++编写的ROS2节点程序一定需要包含该头文件
#include "std_msgs/msg/string.hpp"//std_msgs/msg/string.hpp是ROS2中字符串消息的头文件，后边我们会周期发布一个HelloWorld的字符串消息，所以需要包含该头文件。

using namespace std::chrono_literals;

/* This example creates a subclass of Node and uses std::bind() to register a
 * member function as a callback from the timer. */

class MinimalPublisher : public rclcpp::Node//通过继承rclcpp::Node节点基类创建节点类MinimalPublisher。代码中的每个this都引用节点。
{
  public:
    MinimalPublisher()//节点类MinimalPublisherd的构造函数
    : Node("minimal_publisher"), count_(0)//将count_变量初始化为0，节点名初始化为“minimal_publisher”
    {
      publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);//构造函数内先创建了一个发布者，发布的话题名是topic，话题消息是String，保存消息的队列长度是10
      timer_ = this->create_wall_timer(500ms, std::bind(&MinimalPublisher::timer_callback, this));//然后创建了一个定时器timer_，做了一个500ms的定时，每次触发定时器后，都会运行回调函数timer_callback。
    }
    /*
    timer_callback是这里的关键，每次触发都会发布一次话题消息。
    
    */
  private:
    void timer_callback()
    {
      auto message = std_msgs::msg::String();// message中保存的字符串是Hello world加一个计数值，
      message.data = "Hello, world! " + std::to_string(count_++);
      RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());//通过RCLCPP_INFO宏函数打印一次日志信息
      publisher_->publish(message);//再通过发布者的publish方法将消息发布出去。
    }
    rclcpp::TimerBase::SharedPtr timer_;
    rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
    size_t count_;//最后是计时器、发布者和计数器字段的声明。
};

//定义完节点类后还需要编写main函数
int main(int argc, char * argv[])
{
    rclcpp::init(argc, argv);//初始化ROS2节点
    //使用rclcpp::spin创建MinimalPublisher，并且进入自旋锁，当退出锁时，就会关闭节点结束了
    rclcpp::spin(std::make_shared<MinimalPublisher>());
    rclcpp::shutdown();
    return 0;
}
